package com.demo.function.shiro.jwt;


import com.alibaba.fastjson.JSON;
import com.demo.starter.dto.GeneralResult;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;

/**
 * jwt token过滤器
 */
@Slf4j
public class JWTFilter extends AuthenticatingFilter {
    @Override
    protected AuthenticationToken createToken(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        //获取请求token
        String token = getRequestToken((HttpServletRequest) servletRequest);
        log.info("JWTFilter#createToken: {}", token);
        if(StringUtils.isBlank(token)){
            return null;
        }
        return new JWTToken(token);
    }

    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        //获取请求token，如果token不存在，直接返回401
        String token = getRequestToken((HttpServletRequest) servletRequest);
        log.info("调用JWTFilter#onAccessDenied方法，token: {}", token);
        if(StringUtils.isBlank(token)){
            response(servletResponse, HttpStatus.SC_UNAUTHORIZED, "invalid token");
            return false;
        }

        return executeLogin(servletRequest, servletResponse);
    }

    /**
     * 重写登录失败方法，{@link JWTRealm#doGetAuthenticationInfo}方法报异常时调用
     * @param token token
     * @param e 异常
     * @param request request对象
     * @param response response对象
     * @return  false-登录失败，true-登录成功
     */
    @Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
        log.error("失败异常", e);
        response(response, HttpStatus.SC_INTERNAL_SERVER_ERROR, e.getMessage());
        return false;
    }

    private void response(ServletResponse response, int httpStatus, String msg) {
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.setStatus(httpStatus);
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("application/json; charset=utf-8");
        try {
            String json = JSON.toJSONString(GeneralResult.error(msg));
            httpServletResponse.getWriter().write(json);
        } catch (Exception e) {
            log.error("response异常", e);
        }
    }

    /**
     * 获取请求的token
     */
    private String getRequestToken(HttpServletRequest httpRequest){
        //从header中获取token
        String token = httpRequest.getHeader("token");

        //如果header中不存在token，则从参数中获取token
        if(StringUtils.isBlank(token)){
            token = httpRequest.getParameter("token");
        }

        return token;
    }
}
